﻿#region Using

using Common.Base;

using GameCommon.Base;
using GameCommon.Manager;

using Microsoft.Xna.Framework;

#endregion

namespace GameCommon.Components
{
    public class Camera
    {
        private readonly Size screenSize;

        private bool hasPropertyChanged;

        private Matrix matrix;

        private Position position;

        private float rotation;

        private float scale;

        public Camera()
        {
            this.MinX = 0;
            this.MinY = 0;

            this.Rotation = 0f;
            this.Position = new Position(0, 0);
            this.Scale = 1f;
            this.hasPropertyChanged = true;

            this.CheckMaxPosition = true;
            this.screenSize = Managers.ContentManager.GetViewportSize().Size;
        }

        public bool CheckMaxPosition { get; set; }

        public Matrix Matrix
        {
            get
            {
                return this.matrix;
            }
        }

        public float Scale
        {
            get
            {
                return this.scale;
            }

            set
            {
                this.scale = value;
                this.hasPropertyChanged = true;
            }
        }

        public Position Position
        {
            get
            {
                return this.position;
            }

            private set
            {
                this.position = value;
                this.hasPropertyChanged = true;
            }
        }

        public int X
        {
            get
            {
                return this.position.X;
            }

            set
            {
                if (value < this.MinX || (this.CheckMaxPosition && value > this.MaxX))
                {
                    return;
                }

                this.position.X = value;
                this.hasPropertyChanged = true;
            }
        }

        public int Y
        {
            get
            {
                return this.position.Y;
            }

            set
            {
                if (value < this.MinY || (this.CheckMaxPosition && value > this.MaxY))
                {
                    return;
                }

                this.position.Y = value;
                this.hasPropertyChanged = true;
            }
        }

        public float Rotation
        {
            get
            {
                return this.rotation;
            }

            set
            {
                this.rotation = value;
                this.hasPropertyChanged = true;
            }
        }

        public int MaxX { get; set; }

        public int MaxY { get; set; }

        public int MinX { get; set; }

        public int MinY { get; set; }

        public Size ScreenSize
        {
            get
            {
                return this.screenSize;
            }
        }

        public void UpdateMatrix()
        {
            if (!this.hasPropertyChanged)
            {
                return;
            }

            this.matrix = TransformationMatrix.CreateTranslation(-this.Position, 0) * TransformationMatrix.CreateRotationZ(this.Rotation) * TransformationMatrix.CreateScale(this.Scale);
            this.hasPropertyChanged = false;
        }

        public Position GetPosition(Position pos)
        {
            return new Position(pos) + this.position;
        }
    }
}